home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / crt0.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-25  |  15.4 KB  |  639 lines

  1. /* C code startup routine.
  2.    Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of XEmacs.
  5.  
  6. XEmacs is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by the
  8. Free Software Foundation; either version 2, or (at your option) any
  9. later version.
  10.  
  11. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  12. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with XEmacs; see the file COPYING.  If not, write to the Free
  18. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Synched up with: FSF 19.28. */
  21.  
  22.  
  23. /* The standard Vax 4.2 Unix crt0.c cannot be used for Emacs
  24.    because it makes `envron' an initialized variable.
  25.    It is easiest to have a special crt0.c on all machines
  26.    though I don't know whether other machines actually need it.  */
  27.  
  28. /* On the vax and 68000, in BSD4.2 and USG5.2,
  29.    this is the data format on startup:
  30.   (vax) ap and fp are unpredictable as far as I know; don't use them.
  31.   sp ->  word containing argc
  32.          word pointing to first arg string
  33.      [word pointing to next arg string]... 0 or more times
  34.      0
  35. Optionally:
  36.      [word pointing to environment variable]... 1 or more times
  37.      ...
  38.      0
  39. And always:
  40.      first arg string
  41.      [next arg string]... 0 or more times
  42. */
  43.  
  44. /* On the 16000, at least in the one 4.2 system I know about,
  45.   the initial data format is
  46.   sp ->  word containing argc
  47.          word containing argp
  48.          word pointing to first arg string, and so on as above
  49. */
  50.  
  51. #ifdef emacs
  52. #include <config.h>
  53. #endif
  54.  
  55. #ifdef __GNUC__
  56. #define asm __asm
  57. #endif
  58.  
  59. /* Workaround for Sun cc 3.0, which doesn't handle asm's outside a fn. */
  60. #if __SUNPRO_C >= 0x300
  61. #define no_toplevel_asm
  62. #endif
  63.  
  64. /*        ********  WARNING ********
  65.     Do not insert any data definitions before data_start!
  66.     Since this is the first file linked, the address of the following
  67.     variable should correspond to the start of initialized data space.
  68.     On some systems this is a constant that is independent of the text
  69.     size for shared executables.  On others, it is a function of the
  70.     text size. In short, this seems to be the most portable way to
  71.     discover the start of initialized data space dynamically at runtime,
  72.     for either shared or unshared executables, on either swapping or
  73.     virtual systems.  It only requires that the linker allocate objects
  74.     in the order encountered, a reasonable model for most Unix systems.
  75.     Similarly, note that the address of _start() should be the start
  76.     of text space.   Fred Fish, UniSoft Systems Inc.  */
  77.  
  78. int data_start = 0;
  79.  
  80. #ifdef NEED_ERRNO
  81. int errno;
  82. #endif
  83.  
  84. #ifndef DONT_NEED_ENVIRON
  85. char **environ;
  86. #endif
  87.  
  88. #ifndef static
  89. /* On systems where the static storage class is usable, this function
  90.    should be declared as static.  Otherwise, the static keyword has
  91.    been defined to be something else, and code for those systems must
  92.    take care of this declaration appropriately.  */
  93. static start1 ();
  94. #endif
  95.  
  96. #if defined(orion) || defined(pyramid) || defined(celerity) || defined(ALLIANT) || defined(clipper) || defined(sps7)
  97.  
  98. #if defined(sps7) && defined(V3x)
  99.         asm("    section    10");
  100.         asm("    ds.b    0xb0");
  101. #endif
  102.  
  103. #ifdef ALLIANT
  104. /* _start must initialize _curbrk and _minbrk on the first startup;
  105.    when starting up after dumping, it must initialize them to what they were
  106.    before the dumping, since they are in the shared library and
  107.    are not dumped.  See ADJUST_EXEC_HEADER in m-alliant.h.  */
  108. extern unsigned char *_curbrk, *_minbrk;
  109. extern unsigned char end;
  110. unsigned char *_setbrk = &end;
  111. #ifdef ALLIANT_2800
  112. unsigned char *_end = &end;
  113. #endif
  114. #endif
  115.  
  116. #ifndef DUMMIES
  117. #define DUMMIES
  118. #endif
  119.  
  120. _start (DUMMIES argc, argv, envp)
  121.      int argc;
  122.      char **argv, **envp;
  123. {
  124. #ifdef ALLIANT
  125. #ifdef ALLIANT_2800
  126.   _curbrk = _end;
  127.   _minbrk = _end;
  128. #else
  129.   _curbrk = _setbrk;
  130.   _minbrk = _setbrk;
  131. #endif
  132. #endif
  133.  
  134.   environ = envp;
  135.  
  136.   exit (main (argc, argv, envp));
  137. }
  138.  
  139. #endif /* orion or pyramid or celerity or alliant or clipper */
  140.  
  141. #if defined (ns16000) && !defined (sequent) && !defined (UMAX) && !defined (CRT0_DUMMIES)
  142.  
  143. _start ()
  144. {
  145. /* On 16000, _start pushes fp onto stack */
  146.   start1 ();
  147. }
  148.  
  149. /* ignore takes care of skipping the fp value pushed in start.  */
  150. static
  151. start1 (ignore, argc, argv)
  152.      int ignore;
  153.      int argc;
  154.      char **argv;
  155. {
  156.   environ = argv + argc + 1;
  157.  
  158.   if (environ == *argv)
  159.     environ--;
  160.   exit (main (argc, argv, environ));
  161. }
  162. #endif /* ns16000, not sequent and not UMAX, and not the CRT0_DUMMIES method */
  163.  
  164. #ifdef UMAX
  165. _start()
  166. {
  167.     asm("    exit []            # undo enter");
  168.     asm("    .set    exitsc,1");
  169.     asm("    .set    sigcatchall,0x400");
  170.  
  171.     asm("    .globl    _exit");
  172.     asm("    .globl    start");
  173.     asm("    .globl    __start");
  174.     asm("    .globl    _main");
  175.     asm("    .globl    _environ");
  176.     asm("    .globl    _sigvec");
  177.     asm("    .globl    sigentry");
  178.  
  179.     asm("start:");
  180.     asm("    br    .xstart");
  181.     asm("    .org    0x20");
  182.     asm("    .double    p_glbl,0,0xf00000,0");
  183.     asm("    .org    0x30");
  184.     asm(".xstart:");
  185.     asm("    adjspb    $8");
  186.     asm("    movd    8(sp),0(sp)    # argc");
  187.     asm("    addr    12(sp),r0");
  188.     asm("    movd    r0,4(sp)    # argv");
  189.     asm("L1:");
  190.     asm("    movd    r0,r1");
  191.     asm("    addqd    $4,r0");
  192.     asm("    cmpqd    $0,0(r1)    # null args term ?");
  193.     asm("    bne    L1");
  194.     asm("    cmpd    r0,0(4(sp))    # end of 'env' or 'argv' ?");
  195.     asm("    blt    L2");
  196.     asm("    addqd    $-4,r0        # envp's are in list");
  197.     asm("L2:");
  198.     asm("    movd    r0,8(sp)    # env");
  199.     asm("    movd    r0,@_environ    # indir is 0 if no env ; not 0 if env");
  200.     asm("    movqd    $0,tos        # setup intermediate signal handler");
  201.     asm("    addr    @sv,tos");
  202.     asm("    movzwd    $sigcatchall,tos");
  203.     asm("    jsr    @_sigvec");
  204.     asm("    adjspb    $-12");
  205.     asm("    jsr    @_main");
  206.     asm("    adjspb    $-12");
  207.     asm("    movd    r0,tos");
  208.     asm("    jsr    @_exit");
  209.     asm("    adjspb    $-4");
  210.     asm("    addr    @exitsc,r0");
  211.     asm("    svc");
  212.     asm("    .align    4        # sigvec arg");
  213.     asm("sv:");
  214.     asm("    .double    sigentry");
  215.     asm("    .double    0");
  216.     asm("    .double    0");
  217.  
  218.     asm("    .comm    p_glbl,1");
  219. }
  220. #endif /* UMAX */
  221.  
  222. #ifdef CRT0_DUMMIES
  223.  
  224. /* Define symbol "start": here; some systems want that symbol.  */
  225. #ifdef DOT_GLOBAL_START
  226. asm("    .text        ");
  227. asm("    .globl start    ");
  228. asm("    start:        ");
  229. #endif /* DOT_GLOBAL_START */
  230.  
  231. #ifdef NODOT_GLOBAL_START
  232. asm("    text        ");
  233. asm("    global start    ");
  234. asm("    start:        ");
  235. #endif /* NODOT_GLOBAL_START */
  236.  
  237. #ifdef m68000
  238.  
  239. /* GCC 2.1, when optimization is turned off, seems to want to push a
  240.    word of garbage on the stack, which screws up the CRT0_DUMMIES
  241.    hack.  So we hand-code _start in assembly language.  */
  242. asm(".text            ");
  243. #ifndef sony_news
  244.   asm("    .even            ");
  245. #else /* sony_news (not gas) */
  246. + asm("    .align 2        ");
  247. #endif /* sony_news (not gas) */
  248. asm(".globl __start        ");
  249. asm("__start:            ");
  250. asm("    link a6,#0        ");
  251. asm("    jbsr _start1        ");
  252. asm("    unlk a6            ");
  253. asm("    rts            ");
  254.  
  255. #else /* not m68000 */
  256.  
  257. _start ()
  258. {
  259. /* On vax, nothing is pushed here  */
  260. /* On sequent, bogus fp is pushed here  */
  261.   start1 ();
  262. }
  263.  
  264. #endif /* possibly m68000 */
  265.  
  266. #ifdef __bsdi__ /* for version number */
  267. #include <sys/param.h>
  268. #endif
  269. #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
  270. char *__progname;
  271. #endif
  272. static
  273. start1 (CRT0_DUMMIES argc, xargv)
  274.      int argc;
  275.      char *xargv;
  276. {
  277.   char **argv = &xargv;
  278.   environ = argv + argc + 1;
  279. #if defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199501)
  280.   __progname = argv[0];
  281. #endif
  282.  
  283.   if ((char *)environ == xargv)
  284.     environ--;
  285.   exit (main (argc, argv, environ));
  286. }
  287. #else /* not CRT0_DUMMIES */
  288.  
  289. /* "m68k" and "m68000" both stand for m68000 processors,
  290.    but with different program-entry conventions.
  291.    This is a kludge.  Now that the CRT0_DUMMIES mechanism above exists,
  292.    most of these machines could use the vax code above
  293.    with some suitable definition of CRT0_DUMMIES.
  294.    Then the symbol m68k could be flushed.
  295.    But I don't want to risk breaking these machines
  296.    in a version 17 patch release, so that change is being put off.  */
  297.  
  298. #ifdef m68k            /* Can't do it all from C */
  299.     asm ("    global    _start");
  300.     asm ("    text");
  301.     asm ("_start:");
  302. #ifndef NU
  303. #ifdef STRIDE
  304.     asm ("    comm    havefpu%,2");
  305. #else /* m68k, not STRIDE */
  306.     asm ("  comm    splimit%,4");
  307. #endif /* STRIDE */
  308.     asm ("    global    exit");
  309.     asm ("    text");
  310. #ifdef STRIDE
  311.     asm ("    trap    &3");
  312.     asm ("    mov.w    %d0,havefpu%");
  313. #else /* m68k, not STRIDE */
  314.       asm ("    mov.l    %d0,splimit%");
  315. #endif /* STRIDE */
  316. #endif /* not NU */
  317.     asm ("    jsr    start1");
  318.     asm ("    mov.l    %d0,(%sp)");
  319.     asm ("    jsr    exit");
  320.     asm ("    mov.l    &1,%d0");    /* d0 = 1 => exit */
  321.     asm ("    trap    &0");
  322. #else /* m68000, not m68k */
  323.  
  324. #ifdef m68000
  325.  
  326. #ifdef ISI68K
  327. /* Added by ESM Sun May 24 12:44:02 1987 to get new ISI library to work */
  328. /* Edited by Ray Mon May 15 15:59:56 EST 1989 so we can compile with gcc */
  329. #if defined(BSD4_3) && !defined(__GNUC__)
  330. static foo () {
  331. #endif
  332.     asm ("    .globl  is68020");
  333.     asm ("is68020:");
  334. #ifndef BSD4_3
  335.     asm ("    .long   0x00000000");
  336.     asm ("    .long   0xffffffff");
  337. /* End of stuff added by ESM */
  338. #endif
  339.     asm ("    .text");
  340.     asm ("    .globl    __start");
  341.     asm ("__start:");
  342.     asm ("    .word 0");
  343.     asm ("    link    a6,#0");
  344.     asm ("    jbsr    _start1");
  345.     asm ("    unlk    a6");
  346.     asm ("    rts");
  347. #if defined(BSD4_3) && !defined(__GNUC__)
  348.       }
  349. #endif
  350. #else /* not ISI68K */
  351.  
  352. _start ()
  353. {
  354. #ifdef sun
  355. #ifdef LISP_FLOAT_TYPE
  356.   finitfp_();
  357. #endif
  358. #endif     
  359. /* On 68000, _start pushes a6 onto stack  */
  360.   start1 ();
  361. }
  362. #endif /* not ISI68k */
  363. #endif /* m68000 */
  364. #endif /* m68k */
  365.  
  366. #if defined(m68k) || defined(m68000)
  367. /* ignore takes care of skipping the a6 value pushed in start.  */
  368. static
  369. #if defined(m68k)
  370. start1 (argc, xargv)
  371. #else
  372. start1 (ignore, argc, xargv)
  373. #endif
  374.      int argc;
  375.      char *xargv;
  376. {
  377.   char **argv = &xargv;
  378.   environ = argv + argc + 1;
  379.  
  380.   if ((char *)environ == xargv)
  381.     environ--;
  382. #ifdef sun_68881
  383.   asm("    jsr     f68881_used");
  384. #endif
  385. #ifdef sun_fpa
  386.   asm("    jsr     ffpa_used");
  387. #endif
  388. #ifdef sun_soft
  389.   asm("    jsr     start_float");
  390. #endif
  391.   exit (main (argc, argv, environ));
  392. }
  393.  
  394. #endif /* m68k or m68000 */
  395.  
  396. #endif /* not CRT0_DUMMIES */
  397.  
  398. #ifdef hp9000s300
  399. int argc_value;
  400. char **argv_value;
  401. #ifdef OLD_HP_ASSEMBLER
  402.     asm("   text");
  403.     asm("    globl __start");
  404.     asm("    globl _exit");
  405.     asm("    globl _main");
  406.     asm("__start");
  407.     asm("    dc.l    0");
  408.     asm("    subq.w    #0x1,d0");
  409.     asm("    move.w    d0,float_soft");
  410.     asm("    move.l    0x4(a7),d0");
  411.     asm("    beq.s    skip_1");
  412.     asm("    move.l    d0,a0");
  413.     asm("    clr.l    -0x4(a0)");
  414.     asm("skip_1");
  415.     asm("    move.l    a7,a0");
  416.     asm("    subq.l    #0x8,a7");
  417.     asm("    move.l    (a0),(a7)");
  418.     asm("    move.l    (a0),_argc_value");
  419.     asm("    addq.l    #0x4,a0");
  420.     asm("    move.l    a0,0x4(a7)");
  421.     asm("    move.l    a0,_argv_value");
  422.     asm("incr_loop");
  423.     asm("    tst.l    (a0)+");
  424.     asm("    bne.s    incr_loop");
  425.     asm("    move.l    0x4(a7),a1");
  426.     asm("    cmp.l    (a1),a0");
  427.     asm("    blt.s    skip_2");
  428.     asm("    subq.l    #0x4,a0");
  429.     asm("skip_2");
  430.     asm("    move.l    a0,0x8(a7)");
  431.     asm("    move.l    a0,_environ");
  432.     asm("    jsr    _main");
  433.     asm("    addq.l    #0x8,a7");
  434.     asm("    move.l    d0,-(a7)");
  435.     asm("    jsr    _exit");
  436.     asm("    move.w    #0x1,d0");
  437.     asm("    trap    #0x0");
  438.     asm("    comm    float_soft,4");
  439. /* float_soft is allocated in this way because C would
  440.    put an underscore character in its name otherwise. */
  441.  
  442. #else /* new hp assembler */
  443.  
  444.     asm("    text");
  445.         asm("   global  float_loc");
  446.         asm("   set     float_loc,0xFFFFB000");
  447.      asm("    global    fpa_loc");
  448.     asm("    set    fpa_loc,0xfff08000");
  449.     asm("    global    __start");
  450.     asm("    global    _exit");
  451.     asm("    global    _main");
  452.     asm("__start:");
  453.     asm("    byte    0,0,0,0");
  454.     asm("    subq.w    &1,%d0");
  455.     asm("    mov.w    %d0,float_soft");
  456.     asm("    mov.w    %d1,flag_68881");
  457. #ifndef HPUX_68010
  458.     asm("    beq.b    skip_float");
  459.     asm("    fmov.l    &0x7400,%fpcr");
  460. /*    asm("    fmov.l    &0x7480,%fpcr"); */
  461. #endif /* HPUX_68010 */
  462.     asm("skip_float:");
  463.     asm("    mov.l    %a0,%d0");
  464.     asm("    add.l    %d0,%d0");
  465.     asm("    subx.w    %d1,%d1");
  466.     asm("    mov.w    %d1,flag_68010");
  467.     asm("    add.l    %d0,%d0");
  468.     asm("    subx.w    %d1,%d1");
  469.     asm("    mov.w    %d1,flag_fpa");
  470.     asm("    tst.l    %d2");
  471.     asm("    ble.b    skip_3");
  472.     asm("    lsl    flag_68881");
  473.     asm("    lsl    flag_fpa");
  474.     asm("skip_3:");
  475.     asm("    mov.l    4(%a7),%d0");
  476.     asm("    beq.b    skip_1");
  477.     asm("    mov.l    %d0,%a0");
  478.     asm("    clr.l    -4(%a0)");
  479.     asm("skip_1:");
  480.     asm("    mov.l    %a7,%a0");
  481.     asm("    subq.l    &8,%a7");
  482.     asm("    mov.l    (%a0),(%a7)");
  483.     asm("    mov.l    (%a0),_argc_value");
  484.     asm("    addq.l    &4,%a0");
  485.     asm("    mov.l    %a0,4(%a7)");
  486.     asm("    mov.l    %a0,_argv_value");
  487.     asm("incr_loop:");
  488.     asm("    tst.l    (%a0)+");
  489.     asm("    bne.b    incr_loop");
  490.     asm("    mov.l    4(%a7),%a1");
  491.     asm("    cmp.l    %a0,(%a1)");
  492.     asm("    blt.b    skip_2");
  493.     asm("    subq.l    &4,%a0");
  494.     asm("skip_2:");
  495.     asm("    mov.l    %a0,8(%a7)");
  496.     asm("    mov.l    %a0,_environ");
  497.     asm("    jsr    _main");
  498.     asm("    addq.l    &8,%a7");
  499.     asm("    mov.l    %d0,-(%a7)");
  500.     asm("    jsr    _exit");
  501.     asm("    mov.w    &1,%d0");
  502.     asm("    trap    &0");
  503.     asm("    comm    float_soft, 4");
  504.     asm("    comm    flag_68881, 4");
  505.     asm("    comm    flag_68010, 4");
  506.     asm("    comm    flag_fpa, 4");
  507.  
  508. #endif /* new hp assembler */
  509. #endif /* hp9000s300 */
  510.  
  511. #ifdef GOULD
  512.  
  513. /* startup code has to be in near text rather
  514.    than fartext as allocated by the C compiler. */
  515.     asm("    .text");
  516.     asm("    .align    2");
  517.     asm("    .globl    __start");
  518.     asm("    .text");
  519.     asm("__start:");
  520. /* setup base register b1 (function base). */
  521.     asm("    .using    b1,.");
  522.     asm("    tpcbr    b1");
  523. /* setup base registers b3 through b7 (data references). */
  524.     asm("    file    basevals,b3");
  525. /* setup base register b2 (stack pointer); it should be
  526.    aligned on a 8-word boundary; but because it is pointing
  527.    to argc, its value should be remembered (in r5). */
  528.     asm("    movw    b2,r4");
  529.     asm("    movw    b2,r5");
  530.     asm("    andw    #~0x1f,r4");
  531.     asm("    movw    r4,b2");
  532. /* allocate stack frame to do some work. */
  533.     asm("    subea    16w,b2");
  534. /* initialize signal catching for UTX/32 1.2; this is
  535.    necessary to make restart from saved image work. */
  536.     asm("    movea    sigcatch,r1");
  537.     asm("    movw    r1,8w[b2]");
  538.     asm("    svc    #1,#150");
  539. /* setup address of argc for start1. */
  540.     asm("    movw    r5,8w[b2]");
  541.     asm("   func    #1,_start1");
  542.     asm("    halt");
  543. /* space for ld to store base register initial values. */
  544.     asm("    .align    5");
  545.     asm("basevals:");
  546.     asm("    .word    __base3,__base4,__base5,__base6,__base7");
  547.  
  548. static
  549. start1 (xargc)
  550.      int *xargc;
  551. {
  552.   int    argc;
  553.   char **argv;
  554.  
  555.   argc = *xargc;
  556.   argv = (char **)(xargc) + 1;
  557.   environ = argv + argc + 1;
  558.  
  559.   if (environ == argv)
  560.     environ--;
  561.   exit (main (argc, argv, environ));
  562.  
  563. }
  564.  
  565. #endif /* GOULD */
  566.  
  567. #ifdef elxsi
  568. #include <elxsi/argvcache.h>
  569.  
  570. extern char **environ;
  571. extern int    errno;
  572. extern void    _init_doscan(), _init_iob();
  573. extern char    end[];
  574. char        *_init_brk = end;
  575.  
  576. _start()
  577. {
  578.   environ = exec_cache.ac_envp;
  579.   brk (_init_brk);
  580.   errno = 0;
  581.   _init_doscan ();
  582.   _init_iob ();
  583.   _exit (exit (main (exec_cache.ac_argc,
  584.              exec_cache.ac_argv,
  585.              exec_cache.ac_envp)));
  586. }
  587. #endif /* elxsi */
  588.  
  589.  
  590. #ifdef sparc
  591. #ifdef no_toplevel_asm
  592. static no_toplevel_asm_wrapper() {
  593. #ifdef USG5_4
  594. asm (".pushsection \".text\"");
  595. #endif /* USG5_4 */
  596. #endif /* no_toplevel_asm */
  597. #ifdef USG5_4
  598. asm (".global _start");
  599. asm (".text");
  600. asm ("_start:");
  601. asm ("    mov    0, %fp");
  602. asm ("    ld    [%sp + 64], %o0");
  603. asm ("    add    %sp, 68, %o1");
  604. asm ("    sll    %o0, 2,    %o2");
  605. asm ("    add    %o2, 4,    %o2");
  606. asm ("    add    %o1, %o2, %o2");
  607. asm ("    sethi    %hi(_environ), %o3");
  608. asm ("    st    %o2, [%o3+%lo(_environ)]");
  609. asm ("    andn    %sp, 7,    %sp");
  610. asm ("    call    main");
  611. asm ("    sub    %sp, 24, %sp");
  612. asm ("    call    _exit");
  613. asm ("    nop");
  614. #else
  615. asm (".global __start");
  616. asm (".text");
  617. asm ("__start:");
  618. asm ("    mov    0, %fp");
  619. asm ("    ld    [%sp + 64], %o0");
  620. asm ("    add    %sp, 68, %o1");
  621. asm ("    sll    %o0, 2,    %o2");
  622. asm ("    add    %o2, 4,    %o2");
  623. asm ("    add    %o1, %o2, %o2");
  624. asm ("    sethi    %hi(_environ), %o3");
  625. asm ("    st    %o2, [%o3+%lo(_environ)]");
  626. asm ("    andn    %sp, 7,    %sp");
  627. asm ("    call    _main");
  628. asm ("    sub    %sp, 24, %sp");
  629. asm ("    call    __exit");
  630. asm ("    nop");
  631. #endif /* USG5_4 */
  632. #ifdef no_toplevel_asm
  633. #ifdef USG5_4
  634. asm (".popsection");
  635. #endif /* USG5_4 */
  636. } /* no_toplevel_asm_wrapper() */
  637. #endif /* no_toplevel_asm */
  638. #endif /* sparc */
  639.